package com.lanou3g.code0417.tickets;

/**
 * Created by dllo on 18/4/17.
 */
//票务中心
public class TicketOffice {
    private int tickets = 100;//有100张票
    private final Object lock = new Object();//final 表示object只能被赋值一次

    //返回值代表是否有票
    public boolean sellticket() {
/*
为了解决线程安全问题,Java引入了同步机制:synchronized
语法:
synchronize(lock){
//只能一时间有一个线程访问
}
大括号内的代码,在同一时间,只能被一个线程调用
即使线程在大括号内停止了,其他线程也无法进入大括号内
小括号内我们称之为 锁 对象,可以是任意对象
但是要注意的是,成为锁对象的对象,不能被改变了
一般的,我们会为锁对象 加上final 防止它改变
加锁效率低但安全,买票的程序将会被锁上变为单线程
锁越小 效率越高
 */
        //同步代码块
        synchronized (lock) { //{}内的代码同一时间只能有一个线程进行,即 锁
            //lock = new Object(); 9行没加final时,加此代码时,会使锁失效
            if (tickets <= 0) {      //object 可以为任何值
                return false;
            }

        /*try {
            //让当前线程停止100毫秒,结果票数可能为负
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
       */

            tickets--;
            //相当于int a = tickets - 1; tickets=a;线程运行时可能在中间停止,引发错误

            //谁卖出去的
            System.out.println(Thread.currentThread().getName() + "卖出一张票,还剩" + tickets + "张");
            //System.out.println("卖出一张票,还剩:" + tickets + "张");
            return true;
        }
    }
    //在方法的返回值前,可以加上synchronized关键字
    //相当于把整个方法都放到同步代码块中
    //不需要写锁对象,这时 锁对象 是 类名.class (这个类的 类对象JVM加载这个类时,自动创建的)
    public synchronized void fun(){}
}
